import math

from app.product.spu.model import Spu as SpuTable
from app.product.spu.model import SpuToUnit as SpuToUnitTable

from exts import db

from app.product.sku.model import SkuToUnit
from app.product.sku.model import Sku
from app.file.model import FileRelation
from common import constant


# ------------- route ------------
def create_spu(is_multiple_spec, is_active, name, sku_sn, spec_string, category_id, brand_id, unit_id, spu_to_units,
               exp, warning_number_low, warning_number_high, barcode, notes, spec_attrs, skus, is_multiple_spec_price,
               unit_prices, sku_unit_prices, image_ids):
    # spu
    new_spu = SpuTable.create(
        name=name, category_id=category_id,
        brand_id=brand_id,
        spec_string=spec_string,
        is_multiple_spec=is_multiple_spec, is_active=is_active,
        notes=notes,
        spec_attrs=spec_attrs,
        exp=exp,
        barcode=barcode,
        is_multiple_spec_price=is_multiple_spec_price,
        commit=True,
    )
    # images
    if image_ids or len(image_ids) == 0:
        for image_id in image_ids:
            FileRelation.create(
                file_id=image_id, belong_id=new_spu.id,
                belong_type=constant.FileBelongType.SPU)
    # 主单位
    SpuToUnitTable.create(
        spu_id=new_spu.id, unit_id=unit_id,
        num_of_base_unit=1, is_base_unit=True)
    # 辅助单位
    if spu_to_units:
        for unit_json in spu_to_units:
            SpuToUnitTable.create(
                spu_id=new_spu.id,
                unit_id=unit_json['unit']['value'],
                num_of_base_unit=unit_json['num_of_base_unit'],
                is_base_unit=False)

    # 单品设置
    new_skus = []
    if not is_multiple_spec:
        one_sku = Sku.create(
            spu_id=new_spu.id,
            spec_attr=None,
            sku_sn=sku_sn,
            barcode=barcode,
            warning_number_low=warning_number_low,
            warning_number_high=warning_number_high,
        )
        new_skus.append(one_sku)
    else:
        # 多规格
        for sku_json in skus:
            # todo 检查 sku_sn 是否存在
            new_sku = Sku.create(
                spu_id=new_spu.id,
                spec_attr_ele=sku_json.get('spec_attr_ele'),
                sku_sn=sku_json['sku_sn'],
                barcode=sku_json.get('barcode'),
                warning_number_low=sku_json.get('warning_number_low'),
                warning_number_high=sku_json.get('warning_number_high'),
                notes=sku_json.get('notes'),
                commit=True,
            )
            new_skus.append(new_sku)
            # 更新图片 images
            if sku_json.get('images'):
                for image in sku_json.get('images'):
                    FileRelation.create(
                        file_id=image['id'], belong_id=new_sku.id,
                        belong_type=constant.FileBelongType.SKU)

    db.session.commit()  # id只能缓存1层， 所以这里需要commit先保存sku

    # 价格设置
    if not is_multiple_spec_price:
        # unit_prices 对所有的sku都使用这些价格
        for unit_price in unit_prices:
            for sku in new_skus:
                SkuToUnit.create(
                    sku_id=sku.id,
                    unit_id=unit_price['unit']['value'],
                    purchase_price=unit_price['purchase_price'],
                    sale_price=unit_price['sale_price'],
                )
    else:
        for sku_unit_price in sku_unit_prices:
            # 找到对应的sku
            sku = Sku.query.filter_by(sku_sn=sku_unit_price['sku']['sku_sn']).first()
            SkuToUnit.create(
                sku_id=sku.id,
                unit_id=sku_unit_price['unit']['value'],
                purchase_price=sku_unit_price['purchase_price'],
                sale_price=sku_unit_price['sale_price'],
            )
    db.session.commit()
    return new_spu


def update_spu(obj_id,
               is_multiple_spec, is_active, name, spec_string, category_id, brand_id, unit_id, spu_to_units,
               exp, warning_number_low, warning_number_high, barcode, notes, spec_attrs, skus, is_multiple_spec_price,
               unit_prices, sku_unit_prices, image_ids
               ):
    spu = SpuTable.query.filter_by(id=obj_id).first()
    spu.update(
        name=name, category_id=category_id,
        brand_id=brand_id,
        spec_string=spec_string,
        is_multiple_spec=is_multiple_spec, is_active=is_active,
        notes=notes,
        spec_attrs=spec_attrs,
        exp=exp,
        barcode=barcode,
        is_multiple_spec_price=is_multiple_spec_price,
        commit=True,
    )
    # images
    if image_ids or len(image_ids) == 0:
        # 删除旧的
        old_relations = FileRelation.query.filter_by(
            belong_id=spu.id,
            belong_type=constant.FileBelongType.SPU).all()
        for old_relation in old_relations:
            old_relation.hard_delete()
        # 创建新的
        for image_id in image_ids:
            FileRelation.create(
                file_id=image_id, belong_id=spu.id,
                belong_type=constant.FileBelongType.SPU)

    # 主单位
    main_unit = SpuToUnitTable.query.filter_by(spu_id=spu.id, is_base_unit=True).first()
    main_unit.update(
        unit_id=unit_id
    )
    # 辅助单位
    update_multiple_spu_to_unit(spu_id=spu.id, spu_to_units_json=spu_to_units)

    # 单品设置
    if not is_multiple_spec:
        # 获取第一个sku
        sku = Sku.query.filter_by(spu_id=spu.id).first()
        sku.warning_number_low = warning_number_low
        sku.warning_number_high = warning_number_high
        sku.barcode = barcode
        new_skus = [sku]
    else:
        new_skus = update_skus(spu_id=spu.id, skus=skus)

    # 价格设置
    all_skus = Sku.query.filter_by(spu_id=spu.id).all()  # 所有的单品
    if not is_multiple_spec_price:
        if unit_prices:
            # 删除
            for sku in all_skus:
                sku_to_units = SkuToUnit.query.filter_by(sku_id=sku.id).all()
                for ele in sku_to_units:
                    ele.hard_delete()
            # 新增
            for unit_price in unit_prices:
                for sku in new_skus:
                    SkuToUnit.create(
                        sku_id=sku.id,
                        unit_id=unit_price['unit']['value'],
                        purchase_price=unit_price['purchase_price'],
                        sale_price=unit_price['sale_price'],
                    )
    else:
        # 价格 (全部删除后新增)
        update_multiple_sku_unit_price(spu_id=spu.id, sku_unit_prices=sku_unit_prices)

    db.session.commit()
    return spu


def update_multiple_spu_to_unit(spu_id, spu_to_units_json):
    """ 更新商品单位关系 暂时选择方案1
    方案1：
        1.删除所有关系 2.新增所有关系
    方案2：
        1.存在则更新 2.不存在则新增 3.不该有的则删除
    :return:
    """
    # 删除
    spu_to_units = SpuToUnitTable.query.filter_by(spu_id=spu_id, is_base_unit=False).all()
    for spu_to_unit in spu_to_units:
        spu_to_unit.hard_delete()

    # 新增
    for unit_json in spu_to_units_json:
        SpuToUnitTable.create(
            spu_id=spu_id,
            unit_id=unit_json['unit']['value'],
            num_of_base_unit=unit_json['num_of_base_unit'],
            is_base_unit=False)


def update_skus(spu_id, skus):
    """ 更新商品单品关系 暂时选择方案1
    方案1：
        1.存在则更新 2.不存在则新增 3.不该有的则删除
    :return:
    """
    sku_sns = [sku_json['sku_sn'] for sku_json in skus]
    new_skus = []
    for sku_json in skus:
        old_sku = Sku.query.filter_by(
            spu_id=spu_id, sku_sn=sku_json['sku_sn']).first()
        if old_sku:
            # 更新
            old_sku.update(
                spec_attr_ele=sku_json.get('spec_attr_ele'),
                barcode=sku_json.get('barcode'),
                warning_number_low=sku_json.get('warning_number_low'),
                warning_number_high=sku_json.get('warning_number_high'),
                notes=sku_json.get('notes'),
            )
            new_skus.append(old_sku)
            # 更新图片 images
            if sku_json.get('images'):
                # 删除旧的
                old_relations = FileRelation.query.filter_by(
                    belong_id=old_sku.id,
                    belong_type=constant.FileBelongType.SKU).all()
                for old_relation in old_relations:
                    old_relation.hard_delete()
                for image in sku_json.get('images'):
                    FileRelation.create(
                        file_id=image['id'], belong_id=old_sku.id,
                        belong_type=constant.FileBelongType.SKU)
        else:
            # 新增
            new_sku = Sku.create(
                spu_id=spu_id,
                spec_attr_ele=sku_json.get('spec_attr_ele'),
                barcode=sku_json.get('barcode'),
                sku_sn=sku_json['sku_sn'],
                warning_number_low=sku_json.get('warning_number_low'),
                warning_number_high=sku_json.get('warning_number_high'),
                notes=sku_json.get('notes'),
            )
            new_skus.append(new_sku)
            # 更新图片 images
            if sku_json.get('images'):
                for image in sku_json.get('images'):
                    FileRelation.create(
                        file_id=image['id'], belong_id=new_sku.id,
                        belong_type=constant.FileBelongType.SKU)
    # 不该有的
    del_skus = Sku.query.filter(Sku.sku_sn.notin_(sku_sns)).filter_by(spu_id=spu_id).all()
    for del_sku in del_skus:
        del_sku.hard_delete()
    return new_skus


def update_multiple_sku_unit_price(spu_id, sku_unit_prices):
    """ 更新单品价格 暂时选择方案1
    方案1：
        1.删除所有单品价格 2.新增所有单品价格
    :return:
    """
    # 删除
    all_skus = Sku.query.filter_by(spu_id=spu_id).all()  # 所有的单品
    for sku in all_skus:
        sku_to_units = SkuToUnit.query.filter_by(sku_id=sku.id).all()
        for sku_to_unit in sku_to_units:
            sku_to_unit.hard_delete()

    # 新增
    for sku_unit_price in sku_unit_prices:
        # 找到对应的sku
        sku = Sku.query.filter_by(sku_sn=sku_unit_price['sku']['sku_sn']).first()
        SkuToUnit.create(
            sku_id=sku.id,
            unit_id=sku_unit_price['unit']['value'],
            purchase_price=sku_unit_price['purchase_price'],
            sale_price=sku_unit_price['sale_price'],
        )


def generate_sku_sn(auto_sku_sn_prefix, auto_sku_sn_start_index, auto_sku_sn_len):
    return auto_sku_sn_prefix + str(int(math.pow(10, auto_sku_sn_len)) + auto_sku_sn_start_index)[1:]


# ----------- 分割线 ----------------


# def create(user_id, **kwargs):
#     # 创建
#     sku_sn = kwargs.pop('sku_sn')
#     new_obj = SpuTable.create(**kwargs)
#
#     # 创建默认单位关联
#     default_unit = get_default_unit()
#     SpuToUnitTable.create(
#         spu_id=new_obj.id, unit_id=default_unit.id,
#         num_of_base_unit=1, is_base_unit=True)
#
#     # 创建一个sku
#     new_sku = Sku.create(spu_id=new_obj.id, sku_sn=sku_sn)
#     db.session.commit()  # id只能缓存1层， 所以这里需要commit先保存sku
#
#     # 创建sku单位关联
#     SkuToUnit.create(sku_id=new_sku.id, unit_id=default_unit.id)
#     db.session.commit()
#     return new_obj

# new_spu_to_unit = DictMixin.from_dict(SpuToUnitTable, {
#     "spu_id": new_obj.id,
#     "unit_id": default_unit.id,
#     "num_of_base_unit": 1,
#     "is_base_unit": True
# })
# db.session.add(new_spu_to_unit)

# # 创建一个sku
# new_sku = create_sku(user_id, spu_id=new_obj.id, sku_sn=sku_sn)
# db.session.commit()  # id只能缓存1层， 所以这里需要commit先保存sku
#
# # 同时sku单位关联
# new_sku_to_unit = DictMixin.from_dict(SkuToUnit, {
#     "sku_id": new_sku.id,
#     "unit_id": default_unit.id,
# })
# db.session.add(new_sku)
# db.session.add(new_sku_to_unit)
# db.session.commit()
# return new_obj


# def get_by_page(user_id, **kwargs):
#     pagination = dao.get_by_page(**kwargs)
#     pagination = custom_marshal_pagination(pagination)
#     return pagination
#
#
# def get(user_id, obj_id):
#     return SpuTable.query.filter_by(id=obj_id).first()

#
# def _update(user_id, obj_id, **kwargs):
#     obj = SpuTable.query.filter_by(id=obj_id).first()
#     old_obj = deepcopy(obj)
#     new_obj = DictMixin.from_dict(obj, kwargs)
#     new_obj.updater_id = user_id
#     # 当名称发生修改时，自动更新short_name
#     if new_obj.name and old_obj.name != new_obj.name:
#         new_obj.short_name = get_first_letter_pinyin(new_obj.name)
#     return new_obj


# def delete(user_id, obj_id):
#     # 删除spu, 先删除spu和单位的关联，再删除sku
#     # for ele in SpuToUnitTable.query.filter_by(spu_id=obj_id).all():
#     #     db.session.delete(ele)
#
#     obj = SpuTable.query.filter_by(id=obj_id).first()
#     db.session.delete(obj)
#     db.session.commit()
#     return obj.id


# def delete_many(user_id, obj_ids_list):
#     objs = SpuTable.query.filter(SpuTable.id.in_(obj_ids_list)).all()
#     [db.session.delete(u) for u in objs]
#     db.session.commit()
#     return obj_ids_list


# def batch_update(user_id, obj_ids_list, **kwargs):
#     for obj_id in obj_ids_list:
#         _update(user_id, obj_id, **kwargs)
#     db.session.commit()
#     return obj_ids_list


# 修改商品单位关系
# def update_spu_to_unit(spu_id, spu_to_unit_json):
#     # 找到商品所有的SpuToUnit
#     spu_to_units = SpuToUnitTable.query.filter_by(spu_id=spu_id)
#     # 删除后，重建
#     db.session.delete(spu_to_units)
#     for ele in spu_to_unit_json:
#         SpuToUnitTable.create(
#             spu_id=spu_id,
#             **ele
#         )

# new_spu_to_unit = DictMixin.from_dict(SpuToUnitTable, {
#     "spu_id": spu_id,
#     "unit_id": ele.unit_id,
#     "num_of_base_unit": ele.num_of_base_unit,
#     "is_base_unit": ele.is_base_unit
# })
# db.session.add(new_spu_to_unit)


# ------------- temp -------------

from app.product.sku.model import Sku as SkuTable

# def add_skus_by_change_unit_or_spec(spu_id):
#     spu = SpuTable.query.filter_by(id=spu_id).first()
#     # 取出所有sku
#     exist_skus = SkuTable.query.filter_by(spu_id=spu_id).all()
#
#     # 笛卡尔积生成所有sku
#     units = UnitTable.query.filter_by(pu_id=spu_id).all()
#     specs = spu.specifications
#
#     new_sku_list = [{"": "", "unit_id": "1"}, {}]
#
#     pass
#
#
# from app.product.spu.model import Specification as SpecificationTable
# from app.product.spu.model import Attribute as AttributeTable
#
#
# # ------------- 规格 -------------
# def create_spec(user_id, **kwargs):
#     new_obj = DictMixin.from_dict(SpecificationTable, kwargs)
#     new_obj.creator_id = user_id
#     db.session.add(new_obj)
#     db.session.commit()
#     return new_obj
#
#
# # ------------- 属性 -------------
# def create_attr(user_id, **kwargs):
#     new_obj = DictMixin.from_dict(AttributeTable, kwargs)
#     new_obj.creator_id = user_id
#     db.session.add(new_obj)
#     db.session.commit()
#     return new_obj
#
#
# # ------------- 笛卡尔积 -------------
# def calculate_sku_info(specs, units):
#     pass


#
# specs = [[{'机身颜色': '香槟金'}, {'机身颜色': '樱花粉'}], [{'内存': '16G'}, {'内存': '32G'}, {'内存': '64G'}]]
#
# own_specs = []
# for x in itertools.product(*specs):
#     own_spec = {}
#     for ele in x:
#         own_spec.update(ele)
#     own_specs.append(own_spec)
# print(own_specs)
# units = [1, 2]
#
# for x in itertools.product(*[own_specs, units]):
#     own_spec, unit = x
#     print(own_spec)
#     print(unit)
